package com.health.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.health.system.common.exception.TreeDeleteException;
import com.health.system.dto.AuthorizationResourceDTO;
import com.health.system.dto.ResourceTreeListDTO;
import com.health.system.entity.Resource;
import com.health.system.mapper.ResourceMapper;
import com.health.system.service.ResourceService;
import com.health.system.vo.ResourceTreeListSearchVo;
import com.health.system.vo.ResourceVo;
import com.health.system.vo.UpdateStatusVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;


@Service
public class ResourceServiceImpl extends ServiceImpl<ResourceMapper, Resource> implements ResourceService {
    @Autowired
    private ResourceMapper resourceMapper;

    @Override
    public void updateStatus(UpdateStatusVo vo) {
        Resource resource = Resource.builder()
                .id(vo.getId())
                .isAnon(vo.getStatus())
                .build();

        resourceMapper.updateById(resource);
    }

    @Transactional
    @Override
    public void deleteById(Long id) {
        int resource = resourceMapper.selectList(new LambdaQueryWrapper<Resource>().eq(Resource::getParentId, id)).size();

        if (resource > 0) {
            throw new TreeDeleteException();
        }

        resourceMapper.deleteRelationRole(id);
        resourceMapper.deleteById(id);
    }

    @Override
    public void insert(ResourceVo vo) {
        Resource resource = Resource.builder()
                .parentId(vo.getParentId())
                .resourceName(vo.getName())
                .url(vo.getUrl())
                .requestMethod(vo.getRequestMethod())
                .build();

        resourceMapper.insert(resource);
    }

    @Override
    public void update(ResourceVo vo) {
        lambdaUpdate()
                .eq(Resource::getId, vo.getId())
                .set(Resource::getResourceName, vo.getName())
                .set(Resource::getRequestMethod, vo.getRequestMethod())
                .set(Resource::getUrl, vo.getUrl())
                .update();
    }

    @Override
    public List<AuthorizationResourceDTO> getResourcesAndRoles() {
        // TODO：缓存权限信息
        List<AuthorizationResourceDTO> result = resourceMapper.selectResourcesAndRoles();
        return result;
    }

    @Override
    public List<ResourceTreeListDTO> treeList(ResourceTreeListSearchVo condition) {
        List<Resource> resources = resourceMapper.selectList(new LambdaQueryWrapper<Resource>()
                .like(StringUtils.isNotBlank(condition.getKeyword()), Resource::getResourceName, condition.getKeyword()));

        return resources.stream()
                .filter(p -> p.getParentId() == 0L)
                .map(r -> ResourceTreeListDTO.builder()
                        .id(r.getId())
                        .url(r.getUrl())
                        .requestMethod(r.getRequestMethod())
                        .anon(r.isAnon())
                        .createTime(r.getCreateTime())
                        .resourceName(r.getResourceName())
                        .children(getChildren(r.getId(), resources))
                        .build())
                .collect(Collectors.toList());
    }

    private List<ResourceTreeListDTO> getChildren(Long id, List<Resource> data) {
        return data.stream()
                .filter(r -> id.equals(r.getParentId()))
                .map(r -> ResourceTreeListDTO.builder()
                        .id(r.getId())
                        .resourceName(r.getResourceName())
                        .url(r.getUrl())
                        .requestMethod(r.getRequestMethod())
                        .parentId(id)
                        .anon(r.isAnon())
                        .children(getChildren(r.getId(), data))
                        .build())
                .collect(Collectors.toList());
    }
}
